This brief tutorial will introduce you to the basic usage of the AlphaTims API in Python. It is divided in five parts:
If AlphaTims is not installed yet, install it with (NOTE it is highly recommended to do this in a clean conda environment):
#!pip install "alphatims[plotting]"
Import the AlphaTims utils libraries to use it (NOTE: this may take a few seconds):
import alphatims.utils
By default all but one CPU threads are used by AlphaTims. A log file is by default written to the log folder in AlphaTims root directory.
Both uptions can be updated with the commands:
alphatims.utils.set_threads(4)
log_file_name = alphatims.utils.set_logger(
log_file_name="tutorial_log.txt",
overwrite=True
)
To ensure full reproducibility, it is best to always log the details of your AlphaTims installation and OS:
alphatims.utils.show_platform_info()
alphatims.utils.show_python_info()
2021-09-22 09:31:45> Platform information: 2021-09-22 09:31:45> system - Darwin 2021-09-22 09:31:45> release - 19.6.0 2021-09-22 09:31:45> version - 10.15.7 2021-09-22 09:31:45> machine - x86_64 2021-09-22 09:31:45> processor - i386 2021-09-22 09:31:45> cpu count - 8 2021-09-22 09:31:45> cpu frequency - 2300.00 Mhz 2021-09-22 09:31:45> ram - 18.9/32.0 Gb (available/total) 2021-09-22 09:31:45> 2021-09-22 09:31:45> Python information: 2021-09-22 09:31:45> alphatims - 0.3.0 2021-09-22 09:31:45> bokeh - 2.2.3 2021-09-22 09:31:45> click - 8.0.1 2021-09-22 09:31:45> datashader - 0.12.1 2021-09-22 09:31:45> h5py - 3.2.1 2021-09-22 09:31:45> hvplot - 0.7.1 2021-09-22 09:31:45> numba - 0.53.1 2021-09-22 09:31:45> pandas - 1.2.4 2021-09-22 09:31:45> psutil - 5.8.0 2021-09-22 09:31:45> python - 3.8.10 2021-09-22 09:31:45> python-lzf - 0.2.4 2021-09-22 09:31:45> pyzstd - 0.15.0 2021-09-22 09:31:45> selenium - 3.141.0 2021-09-22 09:31:45> tqdm - 4.60.0 2021-09-22 09:31:45>
Now you can load the other AlphaTims libraries. When an editable version is installed with the command (pip install -e alphatims), libraries can interactively be reloaded with the following command when the source code is modified:
import alphatims.bruker
import alphatims.plotting
import importlib
def reload():
importlib.reload(alphatims.utils)
importlib.reload(alphatims.bruker)
importlib.reload(alphatims.plotting)
alphatims.utils.set_threads(4)
alphatims.utils.set_logger(log_file_name="tutorial_log.txt")
# NOTE, calling reload() updates global variables in alphatims.utils,
# so e.g. any alphatims.utils.set_* function need to be redone
# after reloading, unless you specify this in the reload function.
2021-09-22 09:31:45> WARNING: No Bruker libraries are available for this operating system. Intensities are uncalibrated, resulting in (very) small differences. However, mobility and m/z values need to be estimated. While this estimation often returns acceptable results with errors < 0.02 Th, huge errors (e.g. offsets of 6 Th) have already been observed for some samples! 2021-09-22 09:31:45>
Note that AlphaTims is fully documented and that help functions are available, e.g.:
help(alphatims.utils.set_threads)
Help on function set_threads in module alphatims.utils:
set_threads(threads: int, set_global: bool = True) -> int
Parse and set the (global) number of threads.
Parameters
----------
threads : int
The number of threads.
If larger than available cores, it is trimmed to the available maximum.
If 0, it is set to the maximum cores available.
If negative, it indicates how many cores NOT to use.
set_global : bool
If False, the number of threads is only parsed to a valid value.
If True, the number of threads is saved as a global variable.
Default is True.
Returns
-------
: int
The number of threads.
A complete Bruker .d folder (available for download on AlphaTims' GitHub page) can be read into memory with the following command:
IMPORTANT NOTE: available RAM should be roughly twice the size of the Bruker .d folder. This is easily checked with the output of alphatims.utils.show_platform_info()
# reload()
bruker_d_folder_name = "/Users/swillems/Data/alphatims_testing/20201207_tims03_Evo03_PS_SA_HeLa_200ng_EvoSep_prot_DDA_21min_8cm_S1-C10_1_22476.d"
data = alphatims.bruker.TimsTOF(bruker_d_folder_name)
2021-09-22 09:31:48> Importing data from /Users/swillems/Data/alphatims_testing/20201207_tims03_Evo03_PS_SA_HeLa_200ng_EvoSep_prot_DDA_21min_8cm_S1-C10_1_22476.d 2021-09-22 09:31:48> Reading frame metadata for /Users/swillems/Data/alphatims_testing/20201207_tims03_Evo03_PS_SA_HeLa_200ng_EvoSep_prot_DDA_21min_8cm_S1-C10_1_22476.d 2021-09-22 09:31:48> Reading 11,886 frames with 295,251,252 detector events for /Users/swillems/Data/alphatims_testing/20201207_tims03_Evo03_PS_SA_HeLa_200ng_EvoSep_prot_DDA_21min_8cm_S1-C10_1_22476.d
100%|██████████| 11886/11886 [00:02<00:00, 4687.77it/s]
2021-09-22 09:31:51> Indexing /Users/swillems/Data/alphatims_testing/20201207_tims03_Evo03_PS_SA_HeLa_200ng_EvoSep_prot_DDA_21min_8cm_S1-C10_1_22476.d... 2021-09-22 09:31:51> Bruker DLL not available, estimating mobility values 2021-09-22 09:31:51> Bruker DLL not available, estimating mz values 2021-09-22 09:31:51> Indexing quadrupole dimension 2021-09-22 09:31:52> Succesfully imported data from /Users/swillems/Data/alphatims_testing/20201207_tims03_Evo03_PS_SA_HeLa_200ng_EvoSep_prot_DDA_21min_8cm_S1-C10_1_22476.d
In our tutorial, we used MacOS. During our very first command import alphatims.bruker, we noticed a warning message stating that "No Bruker libraries are available [...], mobility and m/z values need to be estimated". For this tutorial dataset these estimations are fine, but in general we advise to use Windows or Linux to avoid estimation. After importing the data on a Windows or Linux PC, it can be saved to a portable HDF file:
hdf_file_name = data.save_as_hdf(
directory=data.directory,
file_name=f"{data.sample_name}.hdf",
overwrite=True
)
2021-09-22 09:31:52> Writing TimsTOF data to /Users/swillems/Data/alphatims_testing/20201207_tims03_Evo03_PS_SA_HeLa_200ng_EvoSep_prot_DDA_21min_8cm_S1-C10_1_22476.hdf.
100%|██████████| 33/33 [00:00<00:00, 40.98it/s]
2021-09-22 09:31:52> Succesfully wrote TimsTOF data to /Users/swillems/Data/alphatims_testing/20201207_tims03_Evo03_PS_SA_HeLa_200ng_EvoSep_prot_DDA_21min_8cm_S1-C10_1_22476.hdf.
This HDF is a single portable file containing all raw data, that can be accessed on all Operating Systems regardless of how it was created. As such, reading of correct mz and mobility values can be done on a Windows or Linux machine, while further processing can be done on any other OS. An additional benefit is that loading of HDF files is roughly three times faster than loading of a raw Bruker .d folder.
A TimsTOF data object can be sliced in the five following dimensions:
In each dimension, you can slice indices with integers and values with floats just as you would do with any normal Python object. Additionally it allows slicing with iterable just as in Numpy. The result of a slicing operation is a pd.DataFrame by default. If the slicing seems confusing, remember that you can always look at the help function.
# help(data)
As a simple example, datapoints for the precursor with index 999 can be obtained by slicing the data in the third (i.e. QUAD) dimension (The first time you slice the data, it can be relatively slow because AlphaTims uses just-in-time (JIT) compilation from the Numba package. All subsequent slices should be a lot faster):
df = data[:100]
df
| raw_indices | frame_indices | scan_indices | precursor_indices | push_indices | tof_indices | rt_values | rt_values_min | mobility_values | quad_low_mz_values | quad_high_mz_values | mz_values | intensity_values | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 0 | 1 | 52 | 0 | 980 | 255432 | 0.564402 | 0.009407 | 1.543966 | -1.000000 | -1.000000 | 913.244436 | 10 |
| 1 | 1 | 1 | 63 | 0 | 991 | 308596 | 0.564402 | 0.009407 | 1.532112 | -1.000000 | -1.000000 | 1185.313597 | 86 |
| 2 | 2 | 1 | 69 | 0 | 997 | 160185 | 0.564402 | 0.009407 | 1.525647 | -1.000000 | -1.000000 | 514.391711 | 159 |
| 3 | 3 | 1 | 77 | 0 | 1005 | 375562 | 0.564402 | 0.009407 | 1.517026 | -1.000000 | -1.000000 | 1578.424884 | 53 |
| 4 | 4 | 1 | 78 | 0 | 1006 | 248581 | 0.564402 | 0.009407 | 1.515948 | -1.000000 | -1.000000 | 880.760590 | 47 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 157710 | 157710 | 99 | 778 | 42 | 92650 | 67395 | 10.970942 | 0.182849 | 0.761638 | 234.168663 | 236.168663 | 235.161356 | 149 |
| 157711 | 157711 | 99 | 780 | 42 | 92652 | 67391 | 10.970942 | 0.182849 | 0.759483 | 234.168663 | 236.168663 | 235.151644 | 97 |
| 157712 | 157712 | 99 | 780 | 42 | 92652 | 67953 | 10.970942 | 0.182849 | 0.759483 | 234.168663 | 236.168663 | 236.518033 | 56 |
| 157713 | 157713 | 99 | 783 | 42 | 92655 | 67395 | 10.970942 | 0.182849 | 0.756250 | 234.168663 | 236.168663 | 235.161356 | 175 |
| 157714 | 157714 | 99 | 791 | 42 | 92663 | 67394 | 10.970942 | 0.182849 | 0.747629 | 234.168663 | 236.168663 | 235.158928 | 161 |
157715 rows × 13 columns
Other slicing options include traditional Python slices or iterables. Multiple dimensions can be defined at the same time, for instance:
df = data[:400.5, 500:700, 0, 400.0: 400.5, [50, 87, 116]]
df
| raw_indices | frame_indices | scan_indices | precursor_indices | push_indices | tof_indices | rt_values | rt_values_min | mobility_values | quad_low_mz_values | quad_high_mz_values | mz_values | intensity_values | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 221445 | 146 | 575 | 0 | 136063 | 126345 | 15.952364 | 0.265873 | 0.980388 | -1.0 | -1.0 | 400.057569 | 87 |
| 1 | 1104358 | 585 | 682 | 0 | 543562 | 126352 | 62.533610 | 1.042227 | 0.865086 | -1.0 | -1.0 | 400.079736 | 50 |
| 2 | 1262646 | 660 | 608 | 0 | 613088 | 126355 | 70.481689 | 1.174695 | 0.944828 | -1.0 | -1.0 | 400.089236 | 87 |
| 3 | 1527863 | 783 | 683 | 0 | 727307 | 126361 | 83.543192 | 1.392387 | 0.864009 | -1.0 | -1.0 | 400.108237 | 50 |
| 4 | 1656733 | 839 | 628 | 0 | 779220 | 126409 | 89.517499 | 1.491958 | 0.923276 | -1.0 | -1.0 | 400.260259 | 116 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 123 | 45061971 | 3697 | 624 | 0 | 3431440 | 126396 | 392.637495 | 6.543958 | 0.927586 | -1.0 | -1.0 | 400.219083 | 50 |
| 124 | 45687885 | 3719 | 634 | 0 | 3451866 | 126409 | 394.969046 | 6.582817 | 0.916810 | -1.0 | -1.0 | 400.260259 | 50 |
| 125 | 46587721 | 3752 | 626 | 0 | 3482482 | 126401 | 398.465090 | 6.641085 | 0.925431 | -1.0 | -1.0 | 400.234920 | 116 |
| 126 | 46594055 | 3752 | 636 | 0 | 3482492 | 126392 | 398.465090 | 6.641085 | 0.914655 | -1.0 | -1.0 | 400.206414 | 87 |
| 127 | 46893656 | 3763 | 617 | 0 | 3492681 | 126401 | 399.630908 | 6.660515 | 0.935129 | -1.0 | -1.0 | 400.234920 | 50 |
128 rows × 13 columns
Alternatively, a (partial) dictionary can be passed that describes the desired coordinates:
df = data[
{
"frame_indices": [1, 191],
"scan_indices": slice(300, 800, 10),
"mz_values": slice(None, 400.5),
"intensity_values": 50,
}
]
df
| raw_indices | frame_indices | scan_indices | precursor_indices | push_indices | tof_indices | rt_values | rt_values_min | mobility_values | quad_low_mz_values | quad_high_mz_values | mz_values | intensity_values | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 11009 | 1 | 690 | 0 | 1618 | 98237 | 0.564402 | 0.009407 | 0.856466 | -1.0 | -1.0 | 316.000994 | 50 |
| 1 | 14688 | 1 | 770 | 0 | 1698 | 94768 | 0.564402 | 0.009407 | 0.770259 | -1.0 | -1.0 | 306.313410 | 50 |
| 2 | 303435 | 191 | 740 | 0 | 177988 | 109139 | 20.743806 | 0.345730 | 0.802586 | -1.0 | -1.0 | 347.427845 | 50 |
Instead of returning a pd.DataFrame, it is also possible to return the raw indices of the ions that satisfy the filter by setting the last element of the slice to "raw":
indices = data[:400.5, 500:700, 0, 400.0: 400.5, [50, 87, 116], "raw"]
indices
array([ 221445, 1104358, 1262646, 1527863, 1656733, 1731685,
1834580, 1881013, 2123968, 2258316, 2560093, 2597723,
4610534, 4847408, 7994516, 8162820, 8437336, 9168710,
9178491, 9647218, 13696960, 14530934, 14902933, 16418582,
16422512, 16631196, 18217831, 18479187, 18726665, 18961259,
19448416, 19454152, 19454153, 19455509, 19456166, 19939773,
19957998, 20188944, 20191530, 20408960, 20419036, 20439657,
20668731, 20888042, 20894013, 20895950, 21158002, 21382721,
21388058, 21624059, 21863018, 23629117, 23865688, 24144170,
24145466, 25199967, 25201267, 25207043, 25736293, 25744631,
25996613, 26003284, 26017674, 26017675, 26803109, 27625200,
27919344, 27933607, 28451309, 28451902, 28474678, 29263587,
29545163, 30042520, 30308123, 30314972, 31129679, 31707287,
31718294, 31726560, 31997128, 32019944, 32566870, 33118131,
33391145, 33412635, 33968835, 34275408, 34580883, 34855018,
35695459, 36278859, 36835753, 37140980, 37433442, 37758349,
37762859, 38050210, 38053684, 38328211, 38618093, 38634438,
38909695, 38923640, 39220630, 39223097, 39784161, 40087198,
40659885, 40669594, 40670949, 40931863, 40959762, 41540560,
41822612, 41825654, 41837864, 42156040, 42996090, 43302248,
43596988, 43864191, 43882481, 45061971, 45687885, 46587721,
46594055, 46893656])
Converting these raw indices to the appropriate coordinates or even a whole pd.DataFrame can be done with convenience functions such as:
coordinate_dict = data.convert_from_indices(
indices,
return_rt_values=True,
return_tof_indices=True
)
coordinate_dict
{'tof_indices': array([126345, 126352, 126355, 126361, 126409, 126415, 126328, 126343,
126391, 126337, 126335, 126427, 126391, 126338, 126387, 126387,
126398, 126401, 126392, 126402, 126397, 126361, 126397, 126408,
126397, 126397, 126396, 126409, 126407, 126395, 126404, 126397,
126405, 126397, 126364, 126404, 126409, 126406, 126395, 126405,
126406, 126382, 126408, 126391, 126392, 126397, 126377, 126399,
126407, 126391, 126403, 126387, 126380, 126385, 126381, 126396,
126396, 126388, 126398, 126409, 126396, 126396, 126375, 126386,
126386, 126407, 126405, 126411, 126396, 126399, 126390, 126379,
126338, 126397, 126407, 126398, 126403, 126411, 126389, 126393,
126405, 126409, 126393, 126385, 126406, 126369, 126405, 126390,
126398, 126398, 126405, 126406, 126389, 126397, 126406, 126387,
126387, 126404, 126397, 126406, 126405, 126388, 126405, 126405,
126374, 126407, 126403, 126405, 126385, 126443, 126384, 126405,
126399, 126385, 126404, 126405, 126392, 126401, 126393, 126386,
126405, 126418, 126393, 126396, 126409, 126401, 126392, 126401],
dtype=uint32),
'rt_values': array([ 15.952364, 62.53361 , 70.481689, 83.543192, 89.517499,
93.439612, 98.741651, 100.032919, 112.54035 , 117.414695,
127.564265, 128.539861, 181.616486, 185.116779, 215.42888 ,
216.594252, 218.928011, 224.75686 , 224.75686 , 228.255341,
253.905582, 258.568707, 260.903007, 269.061553, 269.061553,
270.228397, 278.388836, 279.556035, 280.722093, 281.88576 ,
284.216758, 284.216758, 284.216758, 284.216758, 284.216758,
286.546947, 286.546947, 287.713942, 287.713942, 288.879763,
288.879763, 288.879763, 290.04581 , 291.21097 , 291.21097 ,
291.21097 , 292.376449, 293.541619, 293.541619, 294.707783,
295.873268, 304.034589, 305.201813, 306.365968, 306.365968,
311.03095 , 311.03095 , 311.03095 , 313.364331, 313.364331,
314.528855, 314.528855, 314.528855, 314.528855, 318.026799,
321.525534, 322.68959 , 322.68959 , 325.022786, 325.022786,
325.022786, 328.520427, 329.685302, 332.018241, 333.182612,
333.182612, 336.681116, 339.014098, 339.014098, 339.014098,
340.179476, 340.179476, 342.510083, 344.842494, 346.008036,
346.008036, 348.339887, 349.506183, 350.669559, 351.835915,
355.333532, 357.664273, 359.996934, 361.163244, 362.329056,
363.496709, 363.496709, 364.661721, 364.661721, 365.826367,
366.992833, 366.992833, 368.155896, 368.155896, 369.321814,
369.321814, 371.653634, 372.820294, 375.149367, 375.149367,
375.149367, 376.316335, 376.316335, 378.647557, 379.814536,
379.814536, 379.814536, 380.979401, 384.477247, 385.642353,
386.807969, 387.974738, 387.974738, 392.637495, 394.969046,
398.46509 , 398.46509 , 399.630908])}
df = data.as_dataframe(indices)
df
| raw_indices | frame_indices | scan_indices | precursor_indices | push_indices | tof_indices | rt_values | rt_values_min | mobility_values | quad_low_mz_values | quad_high_mz_values | mz_values | intensity_values | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 221445 | 146 | 575 | 0 | 136063 | 126345 | 15.952364 | 0.265873 | 0.980388 | -1.0 | -1.0 | 400.057569 | 87 |
| 1 | 1104358 | 585 | 682 | 0 | 543562 | 126352 | 62.533610 | 1.042227 | 0.865086 | -1.0 | -1.0 | 400.079736 | 50 |
| 2 | 1262646 | 660 | 608 | 0 | 613088 | 126355 | 70.481689 | 1.174695 | 0.944828 | -1.0 | -1.0 | 400.089236 | 87 |
| 3 | 1527863 | 783 | 683 | 0 | 727307 | 126361 | 83.543192 | 1.392387 | 0.864009 | -1.0 | -1.0 | 400.108237 | 50 |
| 4 | 1656733 | 839 | 628 | 0 | 779220 | 126409 | 89.517499 | 1.491958 | 0.923276 | -1.0 | -1.0 | 400.260259 | 116 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 123 | 45061971 | 3697 | 624 | 0 | 3431440 | 126396 | 392.637495 | 6.543958 | 0.927586 | -1.0 | -1.0 | 400.219083 | 50 |
| 124 | 45687885 | 3719 | 634 | 0 | 3451866 | 126409 | 394.969046 | 6.582817 | 0.916810 | -1.0 | -1.0 | 400.260259 | 50 |
| 125 | 46587721 | 3752 | 626 | 0 | 3482482 | 126401 | 398.465090 | 6.641085 | 0.925431 | -1.0 | -1.0 | 400.234920 | 116 |
| 126 | 46594055 | 3752 | 636 | 0 | 3482492 | 126392 | 398.465090 | 6.641085 | 0.914655 | -1.0 | -1.0 | 400.206414 | 87 |
| 127 | 46893656 | 3763 | 617 | 0 | 3492681 | 126401 | 399.630908 | 6.660515 | 0.935129 | -1.0 | -1.0 | 400.234920 | 50 |
128 rows × 13 columns
AlphaTims' plotting module provides a few convenient plots. Note that they can only be used if the gui option is used during installation (pip install "alphatims[plotting]"). In this tutorial we will also load the holoviews package to save our (interactive) plots.
A key plot that is always useful before diving in the data is a total ion chromatogram (TIC):
tic = alphatims.plotting.tic_plot(data, title=data.sample_name, width=900)
hv.save(tic, "tutorial_tic.html")
tic
Other useful plots include heatmaps in different dimensions. For instance, we can check the calibrant spray that is used for the TIMS:
calibrant_mz = 1221.990637
ppm_error = 5
calibrant_low_mz = calibrant_mz / (1 + ppm_error / 10**6)
calibrant_high_mz = calibrant_mz * (1 + ppm_error / 10**6)
df = data[:, :, :, calibrant_low_mz: calibrant_high_mz]
heatmap = alphatims.plotting.heatmap(
df,
x_axis_label="rt",
y_axis_label="mobility",
title=data.sample_name,
width=900
)
hv.save(heatmap, "tutorial_heatmap.html")
heatmap
Of course we can also investigate 1D plots such as spectra for individual precursors of interest (not that this requires "raw" indices as input and not a pd.DataFrame):
precursor_indices = data[:, :, 9999, "raw"]
spectrum = alphatims.plotting.line_plot(
data,
precursor_indices,
x_axis_label="mz",
width=900
)
hv.save(spectrum, "tutorial_spectrum.html")
spectrum
AlphaTims was developed to access both ddaPASEF and diaPASEF. Importing a DIA sample (available for download on AlphaTims' GitHub page) is done in exactly the same way as importing a DDA sample:
bruker_dia_d_folder_name = "/Users/swillems/Data/alphatims_testing/20201207_tims03_Evo03_PS_SA_HeLa_200ng_EvoSep_prot_high_speed_21min_8cm_S1-C8_1_22474.d"
dia_data = alphatims.bruker.TimsTOF(bruker_dia_d_folder_name)
2021-09-22 09:32:00> Importing data from /Users/swillems/Data/alphatims_testing/20201207_tims03_Evo03_PS_SA_HeLa_200ng_EvoSep_prot_high_speed_21min_8cm_S1-C8_1_22474.d 2021-09-22 09:32:00> Reading frame metadata for /Users/swillems/Data/alphatims_testing/20201207_tims03_Evo03_PS_SA_HeLa_200ng_EvoSep_prot_high_speed_21min_8cm_S1-C8_1_22474.d 2021-09-22 09:32:00> Reading 11,868 frames with 730,564,765 detector events for /Users/swillems/Data/alphatims_testing/20201207_tims03_Evo03_PS_SA_HeLa_200ng_EvoSep_prot_high_speed_21min_8cm_S1-C8_1_22474.d
100%|██████████| 11868/11868 [00:05<00:00, 2294.53it/s]
2021-09-22 09:32:05> Indexing /Users/swillems/Data/alphatims_testing/20201207_tims03_Evo03_PS_SA_HeLa_200ng_EvoSep_prot_high_speed_21min_8cm_S1-C8_1_22474.d... 2021-09-22 09:32:05> Bruker DLL not available, estimating mobility values 2021-09-22 09:32:05> Bruker DLL not available, estimating mz values 2021-09-22 09:32:05> Indexing quadrupole dimension 2021-09-22 09:32:06> Succesfully imported data from /Users/swillems/Data/alphatims_testing/20201207_tims03_Evo03_PS_SA_HeLa_200ng_EvoSep_prot_high_speed_21min_8cm_S1-C8_1_22474.d
With AlphaTims slicing mechanism, it is possible to e.g. manually extract fragment traces from a precursor and overlay them in e.g. a single XIC. An example is the following peptide:
with fragments:
| Seq | # | B | Y | # |
|---|---|---|---|---|
| Y | 1 | 164.07065 | 973.44145 | 7 |
| N | 2 | 278.11358 | 810.37812 | 6 |
| D | 3 | 393.14052 | 696.33520 | 5 |
| T | 4 | 494.18820 | 581.30825 | 4 |
| F | 5 | 641.25661 | 480.26057 | 3 |
| W | 6 | 827.33592 | 333.19216 | 2 |
| K | 7 | 955.43089 | 147.11285 | 1 |
peptide = {
"sequence": "YNDTFWK",
"mz": 487.22439,
"mobility": 0.81,
"rt": 10.011 * 60, #seconds
"charge": 2,
"fragment_mzs": {
"y7": 973.44145,
"y6": 810.37812,
"y5": 696.33520,
"y4": 581.30825,
"y3": 480.26057,
"y2": 333.19216,
"y1": 147.11285,
"b1": 164.07065,
"b2": 278.11358,
"b3": 393.14052,
"b4": 494.18820,
"b5": 641.25661,
"b6": 827.33592,
"b7": 955.43089,
}
}
First, we define the following plotting function.
NOTE: This function is not optimized and hence only defined as an example here in the tutorial instead of as an integral part of AlphaTims. As this functionality focuses more on visualization of already analysed data, we refer you to AlphaViz.
def inspect_peptide(
dia_data,
peptide,
ppm=50,
rt_tolerance=30, #seconds
mobility_tolerance=0.05, #1/k0
heatmap=False
):
precursor_mz = peptide["mz"]
precursor_mobility = peptide["mobility"]
precursor_rt = peptide["rt"]
fragment_mzs = peptide["fragment_mzs"]
rt_slice = slice(
precursor_rt - rt_tolerance,
precursor_rt + rt_tolerance
)
im_slice = slice(
precursor_mobility - mobility_tolerance,
precursor_mobility + mobility_tolerance
)
precursor_mz_slice = slice(
precursor_mz / (1 + ppm / 10**6),
precursor_mz * (1 + ppm / 10**6)
)
precursor_indices = dia_data[
rt_slice,
im_slice,
0, #index 0 means that the quadrupole is not used
precursor_mz_slice,
"raw"
]
if heatmap:
precursor_heatmap = alphatims.plotting.heatmap(
dia_data.as_dataframe(precursor_indices),
x_axis_label="rt",
y_axis_label="mobility",
title="precursor",
width=250,
height=250
)
overlay = precursor_heatmap
else:
precursor_xic = alphatims.plotting.line_plot(
dia_data,
precursor_indices,
x_axis_label="rt",
width=900,
remove_zeros=True,
label="precursor"
)
overlay = precursor_xic
for fragment_name, mz in fragment_mzs.items():
fragment_mz_slice = slice(
mz / (1 + ppm / 10**6),
mz * (1 + ppm / 10**6)
)
fragment_indices = dia_data[
rt_slice,
im_slice,
precursor_mz_slice,
fragment_mz_slice,
"raw"
]
if len(fragment_indices) > 0:
if heatmap:
fragment_heatmap = alphatims.plotting.heatmap(
dia_data.as_dataframe(fragment_indices),
x_axis_label="rt",
y_axis_label="mobility",
title=f"{fragment_name}: {mz:.3f}",
width=250,
height=250,
)
overlay += fragment_heatmap
else:
fragment_xic = alphatims.plotting.line_plot(
dia_data,
fragment_indices,
x_axis_label="rt",
width=900,
remove_zeros=True,
label=fragment_name,
)
overlay *= fragment_xic.opts(muted=True)
if not heatmap:
overlay.opts(hv.opts.Overlay(legend_position='bottom'))
overlay.opts(hv.opts.Overlay(click_policy='mute'))
overlay = overlay.opts(show_legend=True)
hv.save(overlay, "tutorial_dia_xic_overlay.html")
return overlay.opts(
title=f"{peptide['sequence']}_{peptide['charge']}"
)
Plotting overlaying XICs can now be done with a single command. Note that this plot is fully interactive and that e.g. individual fragments can be selected by clicking the legend.
dia_xic_overlay = inspect_peptide(
dia_data,
peptide,
ppm=50,
rt_tolerance=30, #seconds
mobility_tolerance=0.05, #1/k0
)
hv.save(dia_xic_overlay, "tutorial_dia_xic_overlay.html")
dia_xic_overlay
However, timsTOF data also has a mobility dimension. It can be useful to inspect this dimension in combination with the rt dimension. This can be done by supplying the heatmap argument to the inspect_peptide function. Note again that this plot is fully interactive and that zooming and panning is done simultaneously for all subplots.
dia_heatmap_overlay = inspect_peptide(
dia_data,
peptide,
ppm=50,
rt_tolerance=30, #seconds
mobility_tolerance=0.05, #1/k0
heatmap=True
)
hv.save(dia_heatmap_overlay, "tutorial_dia_heatmap_overlay.html")
dia_heatmap_overlay